/**
* Copyright 2020 Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at

* http://www.apache.org/licenses/LICENSE-2.0

* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.

* File sample_process.cpp
* Description: handle acl resource
*/
#include "dimp/dimp_tracking.hpp"
#include <iostream>
#include "dimp/model_process.h"
#include "acl/acl.h"
#include "utils.h"

using namespace std;
using namespace cv;

extern time_t t;


Dimp_Track::Dimp_Track(const char* model_01_path, const char* model_02_path)
:deviceId_(0), context_(nullptr), stream_(nullptr), isInited_(false){
    score_model_path_ = model_01_path;
    iou_model_path_ = model_02_path;
    imageDataSize_ = RGBU8_IMAGE_SIZE(288, 288);
}

Dimp_Track::~Dimp_Track(){
    DestroyResource();
}



Result Dimp_Track::InitModel() {
    Result ret = get_scores_model_.LoadModelFromFileWithMem(score_model_path_);
    if (ret != SUCCESS) {
        ERROR_LOG("execute LoadModelFromFileWithMem failed");
        return FAILED;
    }

    ret = get_scores_model_.CreateDesc();
    if (ret != SUCCESS) {
        ERROR_LOG("execute CreateDesc failed");
        return FAILED;
    }

    ret = get_scores_model_.CreateOutput();
    if (ret != SUCCESS) {
        ERROR_LOG("execute CreateOutput failed");
        return FAILED;
    }

    ret = get_iou_model_.LoadModelFromFileWithMem(iou_model_path_);
    if (ret != SUCCESS) {
        ERROR_LOG("execute LoadModelFromFileWithMem failed");
        return FAILED;
    }

    ret = get_iou_model_.CreateDesc();
    if (ret != SUCCESS) {
        ERROR_LOG("execute CreateDesc failed");
        return FAILED;
    }

    ret = get_iou_model_.CreateOutput();
    if (ret != SUCCESS) {
        ERROR_LOG("execute CreateOutput failed");
        return FAILED;
    }




    return SUCCESS;
}

Result Dimp_Track::CreateInputdDataset_for_ScoreModel()
{

    //Request image data memory for input model
    aclError aclRet = aclrtMalloc(&imageDataBuf_, imageDataSize_, ACL_MEM_MALLOC_HUGE_FIRST);
  //  cout << imageDataSize_<< endl;
    if (aclRet != ACL_ERROR_NONE) {

        ERROR_LOG("malloc imageData buffer failed, aclRet is %d", aclRet);
        return FAILED;
    }

    aclRet = aclrtMalloc(&weightsDatabuf_, 16384, ACL_MEM_MALLOC_HUGE_FIRST);
    if (aclRet != ACL_ERROR_NONE) {

        ERROR_LOG("malloc weightsData buffer failed, aclRet is %d", aclRet);
        return FAILED;
    }



    //Use the applied memory to create the model and input dataset. After creation, only update the memory data for each frame of inference, instead of creating the input dataset every time
    Result ret = get_scores_model_.Create2Inputs(imageDataBuf_, imageDataSize_, weightsDatabuf_, 16384);
    if (ret != SUCCESS) {
        ERROR_LOG("Create mode input dataset failed");
        return FAILED;
    }

    return SUCCESS;
}

Result Dimp_Track::CreateInputdDataset_for_IouModel()
{
    roiboxesSize_ = 50*5*4;
    if (runMode_ == ACL_HOST)
        roiboxesBuf_ = Utils::CopyDataHostToDevice((void *)roiboxes_, roiboxesSize_);
    else
        roiboxesBuf_ = Utils::CopyDataDeviceToDevice((void *)roiboxes_, roiboxesSize_);
    if (roiboxesBuf_ == nullptr) {
        ERROR_LOG("Copy roiboxes to device failed");
        return FAILED;
    }

    aclError aclRet = aclrtMalloc(&layer2DataBuf_, 663552, ACL_MEM_MALLOC_HUGE_FIRST);
    if (aclRet != ACL_ERROR_NONE) {
        ERROR_LOG("malloc layer2 buffer failed, aclRet is %d", aclRet);
        return FAILED;
    }

    aclRet = aclrtMalloc(&layer3DataBuf_, 331776, ACL_MEM_MALLOC_HUGE_FIRST);
    if (aclRet != ACL_ERROR_NONE) {
        ERROR_LOG("malloc layer3 buffer failed, aclRet is %d", aclRet);
        return FAILED;
    }

    aclRet = aclrtMalloc(&modulation1DataBuf_, 1024, ACL_MEM_MALLOC_HUGE_FIRST);
    if (aclRet != ACL_ERROR_NONE) {
        ERROR_LOG("malloc mosulation1 buffer failed, aclRet is %d", aclRet);
        return FAILED;
    }

    aclRet = aclrtMalloc(&modulation2DataBuf_, 1024, ACL_MEM_MALLOC_HUGE_FIRST);
    if (aclRet != ACL_ERROR_NONE) {
        ERROR_LOG("malloc mosulation2 buffer failed, aclRet is %d", aclRet);
        return FAILED;
    }


    //Use the applied memory to create the model and input dataset. After creation, only update the memory data for each frame of inference, instead of creating the input dataset every time
    Result ret = get_iou_model_.Create5Inputs(layer2DataBuf_, 663552, layer3DataBuf_, 331776, modulation1DataBuf_, 1024, modulation2DataBuf_, 1024, roiboxesBuf_, roiboxesSize_);
    if (ret != SUCCESS) {
        ERROR_LOG("Create mode input dataset failed");
        return FAILED;
    }

    return SUCCESS;
}

Result Dimp_Track::Init(int32_t& deviceId, aclrtContext& context, aclrtStream& stream, aclrtRunMode& runMode) {
    //If it is already initialized, it is returned
    if (isInited_) {
        INFO_LOG("Classify instance is initied already!");
        return SUCCESS;
    }


    deviceId_ = deviceId;
    context_ = context;
    stream_ = stream;

    runMode_ = runMode;

    //Initializes the model management instance
    AtlasError ret = InitModel();
    if (ret != SUCCESS) {
        ERROR_LOG("Init model failed");
        return FAILED;
    }
    
    isInited_ = true;

    ret = CreateInputdDataset_for_ScoreModel();
    if (ret != ATLAS_OK) {
        ATLAS_LOG_ERROR("CreateInput for score model failed!");
    }

    ret = CreateInputdDataset_for_IouModel();
    if (ret != ATLAS_OK) {
        ATLAS_LOG_ERROR("CreateInput for iou model failed!");
    }

    return SUCCESS;


}

Result Dimp_Track::LoadInputDataForScoreModel(cv::Mat sample_img, void* weights) {

    aclrtMemcpyKind policy = (runMode_ == ACL_HOST)?
                             ACL_MEMCPY_HOST_TO_DEVICE:ACL_MEMCPY_DEVICE_TO_DEVICE;

    Result ret;

    uint32_t ImgSize = RGBU8_IMAGE_SIZE(288, 288);

    ret = (Result)aclrtMemcpy(imageDataBuf_, imageDataSize_,
                        sample_img.ptr<uint8_t>(), ImgSize, policy);
    if (ret != ACL_ERROR_NONE) {
        ERROR_LOG("Copy image data to device failed.");
        return FAILED;
    }

    ret = (Result)aclrtMemcpy(weightsDatabuf_, 16384,
                            weights, 16384, policy);
    
    if (ret != ACL_ERROR_NONE) {
          ERROR_LOG("Copy weights to device failed.");
          return FAILED;
    }

    
    return SUCCESS;
}

void Dimp_Track::GetIouBoxes(Target_Box init_iou_box) {
    float square_box_sz = sqrt(init_iou_box.size.x * init_iou_box.size.y);
    // cout<<"square_box_sz = "<<square_box_sz<<endl;
    Target_Box rand_factor;
    rand_factor.pos.x = 0.1 * square_box_sz;
    rand_factor.pos.y = 0.1 * square_box_sz;
    rand_factor.size.x = 0.5 * square_box_sz;
    rand_factor.size.y = 0.5 * square_box_sz;
    // cout<<"rand_factor = "<<rand_factor.pos.x<<"+"<<rand_factor.pos.y<<"+"<<rand_factor.size.x<<"+"<<rand_factor.size.y<<endl;
    float minimal_edge_size = int(min(init_iou_box.size.x , init_iou_box.size.y)) / 3;
    // cout<<"minimal_edge_size = "<<minimal_edge_size<<endl;
    float temp_w, temp_h, temp_x, temp_y;
    // cout<<"init_iou_box = "<<init_iou_box.pos.x<<" + "<<init_iou_box.pos.y<<" + "<<init_iou_box.size.x<<" + "<<init_iou_box.size.y<<endl;

    
    // cout<<"***************roibox_************"<<endl;
    roiboxes_[0][0] = float(0);
    roiboxes_[0][1] = init_iou_box.pos.x;
    roiboxes_[0][2] = init_iou_box.pos.y;
    roiboxes_[0][3] = roiboxes_[0][1] + init_iou_box.size.x;
    roiboxes_[0][4] = roiboxes_[0][2] + init_iou_box.size.y;
    // cout<<"roibox_ = "<<roiboxes_[0][0]<<"+"<<roiboxes_[0][1]<<"+"<<roiboxes_[0][2]<<"+"<<roiboxes_[0][3] - roiboxes_[0][1]<<"+"<<roiboxes_[0][4] - roiboxes_[0][2]<<" + "<< 0 <<endl;
    for(int i = 1; i < 50; ++i) {
        switch (i / 10)
        {
        case 0:
            // if (i == 5) {
            //     roiboxes_[i][0] = roiboxes_[0][0];
            //     roiboxes_[i][1] = roiboxes_[0][1];
            //     roiboxes_[i][2] = roiboxes_[0][2];
            //     roiboxes_[i][3] = roiboxes_[0][3];
            //     roiboxes_[i][4] = roiboxes_[0][4];
            //     break;
            // }

            temp_w = rand() % (N + 1) / float(N + 1);
            temp_h = rand() % (N + 1) / float(N + 1);
            temp_x = rand() % (N + 1) / float(N + 1);
            temp_y = rand() % (N + 1) / float(N + 1);
  
            roiboxes_[i][0] = float(0);
            roiboxes_[i][3] = (init_iou_box.size.x + (temp_w - 0.5) * rand_factor.size.x) > minimal_edge_size ? (init_iou_box.size.x + (temp_w - 0.5) * rand_factor.size.x) : minimal_edge_size;
            roiboxes_[i][4] = (init_iou_box.size.y + (temp_h - 0.5) * rand_factor.size.y) > minimal_edge_size ? (init_iou_box.size.y + (temp_h - 0.5) * rand_factor.size.y) : minimal_edge_size;
            roiboxes_[i][1] = init_iou_box.pos.x + init_iou_box.size.x / 2 + (temp_x - 0.5) * rand_factor.pos.x - roiboxes_[i][3] / 2;
            roiboxes_[i][2] = init_iou_box.pos.y + init_iou_box.size.y / 2 + (temp_y - 0.5) * rand_factor.pos.y - roiboxes_[i][4] / 2;
            roiboxes_[i][3] = roiboxes_[i][1] + roiboxes_[i][3];
            roiboxes_[i][4] = roiboxes_[i][2] + roiboxes_[i][4];
           
            break;
        case 1:
            roiboxes_[i][0] = float(0);
            roiboxes_[i][1] = roiboxes_[i%10][1] + 0.05;
            roiboxes_[i][2] = roiboxes_[i%10][2];
            roiboxes_[i][3] = roiboxes_[i%10][3];
            roiboxes_[i][4] = roiboxes_[i%10][4] + 0.05;
            break;
        case 2:
            roiboxes_[i][0] = float(0);
            roiboxes_[i][1] = roiboxes_[i%10][1];
            roiboxes_[i][2] = roiboxes_[i%10][2] + 0.05;
            roiboxes_[i][3] = roiboxes_[i%10][3];
            roiboxes_[i][4] = roiboxes_[i%10][4] + 0.05;
            break;
        case 3:
            roiboxes_[i][0] = float(0);
            roiboxes_[i][1] = roiboxes_[i%10][1];
            roiboxes_[i][2] = roiboxes_[i%10][2];
            roiboxes_[i][3] = roiboxes_[i%10][3] + 0.05;
            roiboxes_[i][4] = roiboxes_[i%10][4];
            break;
        case 4:
            roiboxes_[i][0] = float(0);
            roiboxes_[i][1] = roiboxes_[i%10][1];
            roiboxes_[i][2] = roiboxes_[i%10][2];
            roiboxes_[i][3] = roiboxes_[i%10][3];
            roiboxes_[i][4] = roiboxes_[i%10][4] + 0.05;
            break;
        default:
            cout<<"ERROR!"<<endl;
            break;
        }
        // cout<<"roibox_ = "<<roiboxes_[i][0]<<"+"<<roiboxes_[i][1]<<"+"<<roiboxes_[i][2]<<"+"<<roiboxes_[i][3] - roiboxes_[i][1]<<"+"<<roiboxes_[i][4] - roiboxes_[i][2]<<" + "<< i <<endl;
    }
    // cout<<"*****************************************************"<<endl;
}

// void Dimp_Track::GetIouBoxes(Target_Box init_iou_box) {
//     float square_box_sz = sqrt(init_iou_box.size.x * init_iou_box.size.y);
//     // cout<<"square_box_sz = "<<square_box_sz<<endl;
//     Target_Box rand_factor;
//     rand_factor.pos.x = 0.1 * square_box_sz;
//     rand_factor.pos.y = 0.1 * square_box_sz;
//     rand_factor.size.x = 0.25 * square_box_sz;
//     rand_factor.size.y = 0.25 * square_box_sz;
//     // cout<<"rand_factor = "<<rand_factor.pos.x<<"+"<<rand_factor.pos.y<<"+"<<rand_factor.size.x<<"+"<<rand_factor.size.y<<endl;
//     float minimal_edge_size = int(min(init_iou_box.size.x , init_iou_box.size.y)) / 3;
//     // cout<<"minimal_edge_size = "<<minimal_edge_size<<endl;
//     float temp_w, temp_h, temp_x, temp_y;
//     // cout<<"init_iou_box = "<<init_iou_box.pos.x<<" + "<<init_iou_box.pos.y<<" + "<<init_iou_box.size.x<<" + "<<init_iou_box.size.y<<endl;

    
//     // cout<<"***************roibox_************"<<endl;
//     roiboxes_[0][0] = float(0);
//     roiboxes_[0][1] = init_iou_box.pos.x;
//     roiboxes_[0][2] = init_iou_box.pos.y;
//     roiboxes_[0][3] = roiboxes_[0][1] + init_iou_box.size.x;
//     roiboxes_[0][4] = roiboxes_[0][2] + init_iou_box.size.y;
//     // cout<<"roibox_ = "<<roiboxes_[0][0]<<"+"<<roiboxes_[0][1]<<"+"<<roiboxes_[0][2]<<"+"<<roiboxes_[0][3] - roiboxes_[0][1]<<"+"<<roiboxes_[0][4] - roiboxes_[0][2]<<" + "<< 0 <<endl;
//     for(int i = 1; i < 30; ++i) {

//         temp_w = rand() % (N + 1) / float(N + 1);
//         temp_h = rand() % (N + 1) / float(N + 1);
//         temp_x = rand() % (N + 1) / float(N + 1);
//         temp_y = rand() % (N + 1) / float(N + 1);

//         roiboxes_[i][0] = float(0);
//         roiboxes_[i][3] = (init_iou_box.size.x + (temp_w - 0.5) * rand_factor.size.x) > minimal_edge_size ? (init_iou_box.size.x + (temp_w - 0.5) * rand_factor.size.x) : minimal_edge_size;
//         roiboxes_[i][4] = (init_iou_box.size.y + (temp_h - 0.5) * rand_factor.size.y) > minimal_edge_size ? (init_iou_box.size.y + (temp_h - 0.5) * rand_factor.size.y) : minimal_edge_size;
//         roiboxes_[i][1] = init_iou_box.pos.x + init_iou_box.size.x / 2 + (temp_x - 0.5) * rand_factor.pos.x - roiboxes_[i][3] / 2;
//         roiboxes_[i][2] = init_iou_box.pos.y + init_iou_box.size.y / 2 + (temp_y - 0.5) * rand_factor.pos.y - roiboxes_[i][4] / 2;
//         roiboxes_[i][3] = roiboxes_[i][1] + roiboxes_[i][3];
//         roiboxes_[i][4] = roiboxes_[i][2] + roiboxes_[i][4];
       
        
//         // cout<<"roibox_ = "<<roiboxes_[i][0]<<"+"<<roiboxes_[i][1]<<"+"<<roiboxes_[i][2]<<"+"<<roiboxes_[i][3] - roiboxes_[i][1]<<"+"<<roiboxes_[i][4] - roiboxes_[i][2]<<" + "<< i <<endl;
//     }
//     // cout<<"*****************************************************"<<endl;
// }

Result Dimp_Track::LoadInputDataForIouModelOnce(void* modulation1, void* modulation2, Target_Box init_iou_box) {
    GetIouBoxes(init_iou_box);

    aclrtMemcpyKind policy = (runMode_ == ACL_HOST)?
                             ACL_MEMCPY_HOST_TO_DEVICE:ACL_MEMCPY_DEVICE_TO_DEVICE;

    Result ret;

    ret = (Result)aclrtMemcpy(layer2DataBuf_, 663552,
                            layer2_.firstaddr, 663552, policy);
    
    if (ret != ACL_ERROR_NONE) {
        ERROR_LOG("Copy layer2 to device failed.");
        return FAILED;
    }

    ret = (Result)aclrtMemcpy(layer3DataBuf_, 331776,
                            layer3_.firstaddr, 331776, policy);
    
    if (ret != ACL_ERROR_NONE) {
        ERROR_LOG("Copy layer3 to device failed.");
        return FAILED;
    }

    ret = (Result)aclrtMemcpy(modulation1DataBuf_, 1024,
                            modulation1, 1024, policy);
    
    if (ret != ACL_ERROR_NONE) {
        ERROR_LOG("Copy modulation1 to device failed.");
        return FAILED;
    }

    ret = (Result)aclrtMemcpy(modulation2DataBuf_, 1024,
                            modulation2, 1024, policy);
    
    if (ret != ACL_ERROR_NONE) {
        ERROR_LOG("Copy modulation2 to device failed.");
        return FAILED;
    }


    uint32_t roiboxesSize_ = sizeof(roiboxes_);
    ret = (Result)aclrtMemcpy(roiboxesBuf_, roiboxesSize_,
                            roiboxes_, roiboxesSize_, policy);
    
    if (ret != ACL_ERROR_NONE) {
          ERROR_LOG("Copy roiboxes to device failed.");
          return FAILED;
    }  

    return SUCCESS;
}

Result Dimp_Track::LoadInputDataForIouModelAlways() {
    aclrtMemcpyKind policy = (runMode_ == ACL_HOST)?
                             ACL_MEMCPY_HOST_TO_DEVICE:ACL_MEMCPY_DEVICE_TO_DEVICE;

    Result ret;
    uint32_t roiboxesSize_ = sizeof(roiboxes_);
    ret = (Result)aclrtMemcpy(roiboxesBuf_, roiboxesSize_,
                            roiboxes_, roiboxesSize_, policy);
    
    if (ret != ACL_ERROR_NONE) {
          ERROR_LOG("Copy roiboxes to device failed.");
          return FAILED;
    }  

    return SUCCESS;
}


Result Dimp_Track::InferenceForScores() {
    aclmdlDataset* inferenceOutput;
    //Perform reasoning
    AtlasError ret = aclrtSynchronizeStream(stream_);
    // cout<<"ret = "<<ret<<endl;
    ret = get_scores_model_.Execute(stream_, 0);
    if (ret != SUCCESS) {
        ERROR_LOG("Execute model inference failed");
        return FAILED;
    }
    //Get inference output
    inferenceOutput = get_scores_model_.GetModelOutputData();

    layer2_.firstaddr = GetInferenceOutputItem(layer2_.size, inferenceOutput, 0);
    // cout<<"size of layer2 = "<<layer2_.size<<endl;

    layer3_.firstaddr = GetInferenceOutputItem(layer3_.size, inferenceOutput, 1);
    // cout<<"size of layer3 = "<<layer3_.size<<endl;

    classifier_feat_.firstaddr = GetInferenceOutputItem(classifier_feat_.size, inferenceOutput, 2);
    // cout<<"size of classifer_feat = "<<classifier_feat_.size<<endl;

    scores_.firstaddr = GetInferenceOutputItem(scores_.size, inferenceOutput, 3);
    // cout<<"size of scores_size = "<<scores_.size<<endl;

    // cout << "**************scores*******************"<<endl;
    // float *scoreoutput = (float *)(scores_.firstaddr);
    // for(int i = 0; i < scores_.size / 4; ++i)
    // {
    //     cout<<scoreoutput[i]<<endl;
    // }
    // cout << "**************scores*******************"<<endl;
    // string modelname = "ScoreModel";
    // get_scores_model_.OutputModelResult(modelname);

    return SUCCESS;
}

Result Dimp_Track::InferenceForIou() {
    aclmdlDataset* inferenceOutput;
    // cout<<"********input roi boxes*****************"<<endl;
    // for(int i = 0; i < 50; ++i) {
    //     cout<<"rotboxes = "<<roiboxes_[i][1]<<" + "<<roiboxes_[i][2]<<" + "<< roiboxes_[i][3]<<" + "<<roiboxes_[i][4]<<" +"<< i <<endl;
    // }
    //Perform reasoning
    // cout<<"no"<<endl;
    AtlasError ret = aclrtSynchronizeStream(stream_);
    ret = get_iou_model_.Execute(stream_, 0);
    if (ret != SUCCESS) {
        ERROR_LOG("Execute model inference failed");
        return FAILED;
    }
    //Get inference output
    inferenceOutput = get_iou_model_.GetModelOutputData();

    iou_pred_.firstaddr = GetInferenceOutputItem(iou_pred_.size, inferenceOutput, 0);
    // cout<<"size of iou_pred = "<<iou_pred_.size<<endl;
    // string modelname = "IouModel";
    // get_iou_model_.OutputModelResult(modelname);

    return SUCCESS;
}

Result Dimp_Track::PostProcessForIouModel() {
    
    float *iououtput = (float *)(iou_pred_.firstaddr);
    // cout<<"********prediou*************"<<endl;
    // for(int i = 0 ; i < 50; ++i) {
    //     cout<<"iououput = "<<iououtput[i]<<" + "<< i <<endl;
    // }
    // cout<<"***************************"<<endl;
    float bb_init_wh[2];
    for(int i = 0; i < 10; ++i)
    {
        orig_[i] = (double)iououtput[i];
    }

    for(int i = 10; i < 20; ++i) {
        output_deltax_[i%10] = (iououtput[i] - orig_[i%10]) * 20.0;
        // cout<<"output_deltax = "<<output_deltax_[i % 10]<< " + "<< i%10<<endl;
    }

    for(int i = 20; i < 30; ++i) {
      
        output_deltay_[i%10] = (iououtput[i] - orig_[i%10]) * 20.0;
        // cout<<"output_deltay = "<<output_deltay_[i % 10]<< " + "<< i%10<<endl;
    }

    for(int i = 30; i < 40; ++i) {
        output_deltaw_[i%10] = (iououtput[i] - orig_[i%10]) * 20.0;
        // cout<<"output_deltaw = "<<output_deltaw_[i % 10]<< " + "<< i%10<<endl;
    }

    for(int i = 40; i < 50; ++i) {
        output_deltah_[i%10] = (iououtput[i] - orig_[i%10]) * 20.0;
        // cout<<"output_deltah = "<<output_deltah_[i % 10]<< " + "<< i%10<<endl;
    }

    for(int i = 0; i < 10; ++i) {
        bb_init_wh[0] = roiboxes_[i][3] - roiboxes_[i][1]; 
        bb_init_wh[1] = roiboxes_[i][4] - roiboxes_[i][2];
        // cout<<"w and h = "<<bb_init_wh[0]<<" + "<<bb_init_wh[1]<<endl;
        roiboxes_[i][0] = float(0);
        roiboxes_[i][1] = roiboxes_[i][1] + output_deltax_[i] * bb_init_wh[0];
        roiboxes_[i][2] = roiboxes_[i][2] + output_deltay_[i] * bb_init_wh[1];
        roiboxes_[i][3] = roiboxes_[i][3]  + output_deltaw_[i] * bb_init_wh[0] + output_deltax_[i] * bb_init_wh[0];
        roiboxes_[i][4] = roiboxes_[i][4]  + output_deltah_[i] * bb_init_wh[1] + output_deltay_[i] * bb_init_wh[1];

        // roiboxes_[i][3] = roiboxes_[i][3] + output_deltaw_[i] * bb_init_wh[0];
        // roiboxes_[i][4] = roiboxes_[i][4] + output_deltah_[i] * bb_init_wh[1];

        // cout<<"rotboxes = "<<roiboxes_[i][1]<<" + "<<roiboxes_[i][2]<<" + "<< roiboxes_[i][3]<<" + "<<roiboxes_[i][4]<<" +"<< i <<endl;
    }

    for(int i = 10; i < 20; ++i) {
        roiboxes_[i][0] = float(0);
        roiboxes_[i][1] = roiboxes_[i % 10][1] + 0.05;
        roiboxes_[i][2] = roiboxes_[i % 10][2];
        roiboxes_[i][3] = roiboxes_[i % 10][3] + 0.05;
        roiboxes_[i][4] = roiboxes_[i % 10][4];
    }

    for(int i = 20; i < 30; ++i) {
        roiboxes_[i][0] = float(0);
        roiboxes_[i][1] = roiboxes_[i % 10][1];
        roiboxes_[i][2] = roiboxes_[i % 10][2] + 0.05;
        roiboxes_[i][3] = roiboxes_[i % 10][3];
        roiboxes_[i][4] = roiboxes_[i % 10][4] + 0.05 ;
    }

    for(int i = 30; i < 40; ++i) {
        roiboxes_[i][0] = float(0);
        roiboxes_[i][1] = roiboxes_[i % 10][1];
        roiboxes_[i][2] = roiboxes_[i % 10][2];
        roiboxes_[i][3] = roiboxes_[i % 10][3] + 0.05 ;
        roiboxes_[i][4] = roiboxes_[i % 10][4];
    }

    for(int i = 40; i < 50; ++i) {
        roiboxes_[i][0] = float(0);
        roiboxes_[i][1] = roiboxes_[i % 10][1];
        roiboxes_[i][2] = roiboxes_[i % 10][2];
        roiboxes_[i][3] = roiboxes_[i % 10][3];
        roiboxes_[i][4] = roiboxes_[i % 10][4] + 0.05;
    }


    return SUCCESS;

}

Result Dimp_Track::GetOutputBox() {
    float *iououtput = (float *)(iou_pred_.firstaddr);
    int index[3];
    index[0] = 0;
    float max_score1, max_score2, max_score3, aspect_ratio;
    max_score1 = iououtput[0];
    for(int i = 0; i < 10; ++i) {
        aspect_ratio = float((roiboxes_[i][3] - roiboxes_[i][1])) / float((roiboxes_[i][4] - roiboxes_[i][2]));
        // cout<<"aspect_ratio = "<<aspect_ratio<<endl;
        if((aspect_ratio > 6) || (aspect_ratio < (1.0/6.0))) {
            // cout<<"pass + "<< i <<endl;
            continue;
        }
        if(iououtput[i] >= max_score1) {
            max_score1 = iououtput[i];
            index[0] = i;
            
        }

    }
    // cout<<"index0 = "<<index[0]<<endl;
    // cout<<"max_score0 = "<<max_score1<<endl;
    max_score2 = -100;
    index[1] = index[0];
    for(int i = 0; i < 10; ++i) {
        aspect_ratio = (roiboxes_[i][3] - roiboxes_[i][1]) / (roiboxes_[i][4] - roiboxes_[i][2]);

        if((aspect_ratio > 6) || (aspect_ratio < (1.0/6.0))) {
            // cout<<"pass + "<< i <<endl;
            continue;
        }

        if(i == index[0]) {
            continue;
        }
        if(iououtput[i] > max_score2) {
            max_score2 = iououtput[i];
            index[1] = i;
  
        }
    }
    // cout<<"index1 = "<<index[1]<<endl;
    // cout<<"max_score1 = "<<max_score2<<endl;
    index[2] = index[1];
    max_score3 = -100;
    for(int i = 0; i < 10; ++i) {
        aspect_ratio = (roiboxes_[i][3] - roiboxes_[i][1]) / (roiboxes_[i][4] - roiboxes_[i][2]);

        if((aspect_ratio > 6) || (aspect_ratio < (1.0 / 6.0))) {
            // cout<<"pass + "<< i <<endl;
            continue;
        }
        
        if(i == index[0] || i == index[1]) {
            continue;
        }
        if(iououtput[i] > max_score3) {
            max_score3 = iououtput[i];
            index[2] = i;

        }
    }
    // cout<<"index2 = "<<index[2]<<endl;
    // cout<<"max_score2 = "<<max_score3<<endl;
    predicted_box_.top_left.x = (roiboxes_[index[0]][1] + roiboxes_[index[1]][1] + roiboxes_[index[2]][1]) / 3.0;
    predicted_box_.top_left.y = (roiboxes_[index[0]][2] + roiboxes_[index[1]][2] + roiboxes_[index[2]][2]) / 3.0;
    predicted_box_.bottom_right.x = (roiboxes_[index[0]][3] + roiboxes_[index[1]][3] + roiboxes_[index[2]][3]) / 3.0;
    predicted_box_.bottom_right.y = (roiboxes_[index[0]][4] + roiboxes_[index[1]][4] + roiboxes_[index[2]][4]) / 3.0;
    predicted_iou_ = (max_score1 + max_score2 + max_score3) / 3.0;

    return SUCCESS;
}

// Result Dimp_Track::GetOutputBox() {
//     float *iououtput = (float *)(iou_pred_.firstaddr);
//     int index[5];
//     index[0] = 0;
//     float max_score1, max_score2, max_score3, max_score4, max_score5, aspect_ratio;
//     max_score1 = iououtput[0];
//     for(int i = 0; i < 30; ++i) {
//         aspect_ratio = float((roiboxes_[i][3] - roiboxes_[i][1])) / float((roiboxes_[i][4] - roiboxes_[i][2]));
//         // cout<<"aspect_ratio = "<<aspect_ratio<<endl;
//         if((aspect_ratio > 6) || (aspect_ratio < (1.0/6.0))) {
//             // cout<<"pass + "<< i <<endl;
//             continue;
//         }
//         if(iououtput[i] >= max_score1) {
//             max_score1 = iououtput[i];
//             index[0] = i;
            
//         }

//     }
//     // cout<<"index0 = "<<index[0]<<endl;
//     // cout<<"max_score0 = "<<max_score1<<endl;
//     max_score2 = -100;
//     index[1] = index[0];
//     for(int i = 0; i < 30; ++i) {
//         aspect_ratio = (roiboxes_[i][3] - roiboxes_[i][1]) / (roiboxes_[i][4] - roiboxes_[i][2]);

//         if((aspect_ratio > 6) || (aspect_ratio < (1.0/6.0))) {
//             // cout<<"pass + "<< i <<endl;
//             continue;
//         }

//         if(i == index[0]) {
//             continue;
//         }
//         if(iououtput[i] > max_score2) {
//             max_score2 = iououtput[i];
//             index[1] = i;
  
//         }
//     }
//     // cout<<"index1 = "<<index[1]<<endl;
//     // cout<<"max_score1 = "<<max_score2<<endl;
//     index[2] = index[1];
//     max_score3 = -100;
//     for(int i = 0; i < 10; ++i) {
//         aspect_ratio = (roiboxes_[i][3] - roiboxes_[i][1]) / (roiboxes_[i][4] - roiboxes_[i][2]);

//         if((aspect_ratio > 6) || (aspect_ratio < (1.0 / 6.0))) {
//             // cout<<"pass + "<< i <<endl;
//             continue;
//         }
        
//         if(i == index[0] || i == index[1]) {
//             continue;
//         }
//         if(iououtput[i] > max_score3) {
//             max_score3 = iououtput[i];
//             index[2] = i;

//         }
//     }

//     index[3] = index[2];
//     max_score4 = -100;
//     for(int i = 0; i < 30; ++i) {
//         aspect_ratio = (roiboxes_[i][3] - roiboxes_[i][1]) / (roiboxes_[i][4] - roiboxes_[i][2]);

//         if((aspect_ratio > 6) || (aspect_ratio < (1.0 / 6.0))) {
//             // cout<<"pass + "<< i <<endl;
//             continue;
//         }
        
//         if(i == index[0] || i == index[1] || i == index[2]) {
//             continue;
//         }
//         if(iououtput[i] > max_score4) {
//             max_score4 = iououtput[i];
//             index[3] = i;

//         }
//     }

//     index[4] = index[3];
//     max_score5 = -100;
//     for(int i = 0; i < 10; ++i) {
//         aspect_ratio = (roiboxes_[i][3] - roiboxes_[i][1]) / (roiboxes_[i][4] - roiboxes_[i][2]);

//         if((aspect_ratio > 6) || (aspect_ratio < (1.0 / 6.0))) {
//             // cout<<"pass + "<< i <<endl;
//             continue;
//         }
        
//         if(i == index[0] || i == index[1] || i == index[2] || i == index[3]) {
//             continue;
//         }
//         if(iououtput[i] > max_score5) {
//             max_score5 = iououtput[i];
//             index[4] = i;

//         }
//     }
//     // cout<<"index2 = "<<index[2]<<endl;
//     // cout<<"max_score2 = "<<max_score3<<endl;
//     predicted_box_.top_left.x = (roiboxes_[index[0]][1] + roiboxes_[index[1]][1] + roiboxes_[index[2]][1] + roiboxes_[index[3]][1] + roiboxes_[index[4]][1]) / 5.0;
//     predicted_box_.top_left.y = (roiboxes_[index[0]][2] + roiboxes_[index[1]][2] + roiboxes_[index[2]][2] + roiboxes_[index[3]][2] + roiboxes_[index[4]][2]) / 5.0;
//     predicted_box_.bottom_right.x = (roiboxes_[index[0]][3] + roiboxes_[index[1]][3] + roiboxes_[index[2]][3] + roiboxes_[index[3]][3] + roiboxes_[index[4]][3]) / 5.0;
//     predicted_box_.bottom_right.y = (roiboxes_[index[0]][4] + roiboxes_[index[1]][4] + roiboxes_[index[2]][4] + roiboxes_[index[3]][4] + roiboxes_[index[4]][4]) / 5.0;
//     predicted_iou_ = (max_score1 + max_score2 + max_score3 + max_score4 + max_score5) / 5.0;

//     return SUCCESS;
// }

void* Dimp_Track::GetInferenceOutputItem(uint32_t& itemDataSize,
                                           aclmdlDataset* inferenceOutput,
                                           uint32_t idx) {

    aclDataBuffer* dataBuffer = aclmdlGetDatasetBuffer(inferenceOutput, idx);
    if (dataBuffer == nullptr) {
        ERROR_LOG("Get the %dth dataset buffer from model "
        "inference output failed", idx);
        return nullptr;
    }

    void* dataBufferDev = aclGetDataBufferAddr(dataBuffer);
    if (dataBufferDev == nullptr) {
        ERROR_LOG("Get the %dth dataset buffer address "
        "from model inference output failed", idx);
        return nullptr;
    }

    size_t bufferSize = aclGetDataBufferSize(dataBuffer);
    if (bufferSize == 0) {
        ERROR_LOG("The %dth dataset buffer size of "
        "model inference output is 0", idx);
        return nullptr;
    }

    void* data = nullptr;
    if (runMode_ == ACL_HOST) {
        data = Utils::CopyDataDeviceToLocal(dataBufferDev, bufferSize);
        if (data == nullptr) {
            ERROR_LOG("Copy inference output to host failed");
            return nullptr;
        }
    }
    else {
        data = dataBufferDev;
    }

    itemDataSize = bufferSize;
    return data;
}

void Dimp_Track::DestroyResource()
{	
    get_scores_model_.DestroyResource();
    get_iou_model_.DestroyResource();

    

}
